Skip to content

feat(enterprise): persist agent events and run heartbeats#95

Closed
Gracker wants to merge 2 commits intofeature/enterprise-multi-tenant-cleanup-guardfrom
feature/enterprise-multi-tenant-agent-events
Closed

feat(enterprise): persist agent events and run heartbeats#95
Gracker wants to merge 2 commits intofeature/enterprise-multi-tenant-cleanup-guardfrom
feature/enterprise-multi-tenant-agent-events

Conversation

@Gracker
Copy link
Copy Markdown
Owner

@Gracker Gracker commented May 8, 2026

Summary

  • Persist replayable Agent SSE events in agent_events and serve Last-Event-ID replay before in-memory fallback.
  • Add DB-authoritative analysis_runs.heartbeat_at / updated_at, analysisRunStore, running-run heartbeat updates, and cleanup retention while the persisted heartbeat is fresh.
  • Record local RSS benchmark partial evidence for startup:100MB; §0.4.3 remains blocked on the other 17 matrix cells.

Scope notes

  • Advances the §11.11 rows for terminal AgentEvent replay and abandoned running-run cleanup.
  • Does not close §0.4.12 or §0.4.3; README TODO state is unchanged.

Validation

  • cd backend && PATH="$HOME/.nvm/versions/node/v24.15.0/bin:$PATH" npx jest --runInBand --forceExit src/services/__tests__/analysisRunStore.test.ts src/services/__tests__/agentEventStore.test.ts src/assistant/application/__tests__/assistantApplicationService.test.ts src/services/__tests__/enterpriseSchema.test.ts src/routes/__tests__/agentRoutesRbac.test.ts
  • cd backend && PATH="$HOME/.nvm/versions/node/v24.15.0/bin:$PATH" npm run typecheck
  • cd backend && PATH="$HOME/.nvm/versions/node/v24.15.0/bin:$PATH" npm run test:core
  • PATH="$HOME/.nvm/versions/node/v24.15.0/bin:$PATH" npm run verify:pr

@Gracker Gracker changed the title feat(enterprise): persist replayable agent events feat(enterprise): persist agent events and run heartbeats May 8, 2026
@Gracker
Copy link
Copy Markdown
Owner Author

Gracker commented May 9, 2026

已通过 commit 67856ec (merge) + 023a84a (frontend rebuild) 合入 main,关闭此 PR。

@Gracker Gracker closed this May 9, 2026
yun571 pushed a commit to yun571/SmartPerfetto that referenced this pull request May 11, 2026
Land Plan 44 (Spark Gracker#94, Gracker#95) — project / world memory plus the
feedback → case → skill draft pipeline.

Critical invariant: this contract does NOT modify the existing
session-scope `analysisPatternMemory.ts`. Plan 44 introduces an
independent project + world store at runtime
(`backend/src/agentv3/projectMemory.ts`, landed in D-phase). The
existing 200-entry session store, weighted Jaccard matching, and
supersede integration stay untouched.

Types added to `backend/src/types/sparkContracts.ts`:

- `ProjectMemoryStatus` — 5-state status machine inlined to keep
  `backend/src/types/` independent of `backend/src/agentv3/`. Mirrors
  agentv3's PatternStatus including `disputed_late`. Doc note flags
  that the two unions must stay in sync; if agentv3 changes, mirror
  the change here.
- `ProjectMemoryEntry` — one entry. Carries optional `promotionPolicy`;
  the Plan 44 service layer (`projectMemory.saveProjectMemoryEntry`)
  enforces that a `'world'`-scope entry MUST have a policy. Schema
  itself keeps it optional so older snapshots remain readable.
- `FeedbackPipelineEntry` — feedback pipeline state. Uses the shared
  `CaseRef` from C0 base types so this contract does NOT depend on
  Plan 54's CaseNode shape, breaking the Gracker#44Gracker#54 schema cycle that
  Codex flagged in round 1.
- `MemoryRagSelfImprovementContract` — service surface bundling
  entries + pipeline + recent RAG retrievals.

Storage location for project + world entries:
`backend/logs/analysis_project_memory.json` with shape
`{entries: ProjectMemoryEntry[], promotionAudit: ...}`. Audit log
schema is finalized in §4.3 of the design doc.

Five new test cases in `__tests__/sparkContracts.test.ts` cover:

- ProjectMemoryStatus matches the 5-state machine, no `auto_inferred`
- project entry can omit promotionPolicy
- world entry carries promotionPolicy with reviewer for audit
- FeedbackPipelineEntry uses CaseRef shape, not CaseNode
- contract bundles entries + pipeline + recent retrievals

Test count: 55 (was 50).

Test tier: contract / type-only. `npx tsc --noEmit` clean,
sparkContracts.test.ts passes 55/55. Trace regression intentionally
not run per the tiered policy in commit d8529e1.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
yun571 pushed a commit to yun571/SmartPerfetto that referenced this pull request May 11, 2026
…ew FSM

Plan 44 M1 second slice (Spark Gracker#95). State machine for the
feedback → case_draft → skill_draft → reviewed → merged | rejected
flow. Operator-side only — no MCP tool surface. Storage at
`backend/logs/feedback_pipeline.json` with the same atomic
temp+rename + corruption-safe contract as the other Plan 44 stores.

`backend/src/agentv3/selfImprove/feedbackPipeline.ts`:

- `FeedbackPipeline` class with `createEntry({entryId, feedbackId})`,
  `advance(entryId, opts)`, `getEntry`, `listEntries({stage?})`,
  `removeEntry`, `getStats`.
- Linear FSM with one branch at `reviewed`. ALLOWED_TRANSITIONS
  enforces:
    feedback → {case_draft, rejected}
    case_draft → {skill_draft, rejected}
    skill_draft → {reviewed, rejected}
    reviewed → {merged, rejected}
    merged | rejected → terminal (no transitions)
  Skipping stages, back-edges, and exits-from-terminal all throw.
- Reviewer name required when advancing to reviewed / merged /
  rejected (the three stages where a human signed off). Whitespace
  counts as missing.
- `case` (CaseRef from the C0 base types) and `skillDraftId`
  carried forward across stages — caller can update them per-call;
  prior values survive when not overridden.
- `removeEntry` allows operators to clean up duplicates; terminal
  entries can also be removed since they are no longer in flight.

Monotonic `updatedAt` stamping. `Date.now()` collisions are common
under rapid-fire pipelines (the create + advance + advance sequence
can land in the same ms on modern hardware), so the class tracks a
high-water mark and stamps `Math.max(wall, floor + 1)`. Result:
sort by `updatedAt desc` is deterministic even when wall clock has
not advanced — `listEntries()` reliably surfaces the most-recently-
touched entry first. The floor is reseeded from loaded state so
ordering survives across instances.

Tests (`__tests__/feedbackPipeline.test.ts`): 20 cases covering
createEntry (initial stage, dup rejection), happy-path full-walk
to merged + rejected branch, four illegal transitions (skip,
back-edge, two terminal exits, missing entry), four reviewer
requirement cases, three list/stats cases (recency order, stage
filter, full stats), and three persistence cases (round trip,
corrupted recovery, removeEntry).

Plan 44 M2 still outstanding: admin route POST /api/memory/promote
+ consolidate_to_world_memory admin tool (per §4.5 admin-only,
not host-exposed).

Test tier: CRUD-only service per §5.3. `npx tsc --noEmit` clean,
feedbackPipeline.test.ts passes 20/20. Trace regression
intentionally not run — no agent runtime touched.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant